const Signals = imports.signals;
const BoxPointer = imports.ui.boxpointer;
-const GrabHelper = imports.ui.grabHelper;
const Main = imports.ui.main;
const Params = imports.misc.params;
return Clutter.EVENT_PROPAGATE;
let symbol = event.get_key_symbol();
+
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
this.toggle();
return Clutter.EVENT_STOP;
- } else if (symbol == Clutter.KEY_Escape && this.isOpen) {
- this.close();
- return Clutter.EVENT_STOP;
} else if (symbol == navKey) {
if (!this.isOpen)
this.toggle();
*/
var PopupMenuManager = class {
constructor(owner, grabParams) {
- grabParams = Params.parse(grabParams,
- { actionMode: Shell.ActionMode.POPUP });
- this._grabHelper = new GrabHelper.GrabHelper(owner, grabParams);
+ this._grabParams = Params.parse(grabParams,
+ { actionMode: Shell.ActionMode.POPUP });
+ global.stage.connect('notify::key-focus', () => {
+ if (!this.activeMenu)
+ return;
+
+ let actor = global.stage.get_key_focus();
+ let newMenu = this._findMenuForSource(actor);
+
+ if (newMenu)
+ this._changeMenu(newMenu);
+ });
this._menus = [];
}
menu,
openStateChangeId: menu.connect('open-state-changed', this._onMenuOpenState.bind(this)),
destroyId: menu.connect('destroy', this._onMenuDestroy.bind(this)),
- enterId: 0,
- focusInId: 0,
+ capturedEventId: menu.actor.connect('captured-event', this._onCapturedEvent.bind(this)),
};
- let source = menu.sourceActor;
- if (source) {
- this._grabHelper.addActor(source);
- menudata.enterId = source.connect('enter-event',
- () => this._onMenuSourceEnter(menu));
- menudata.focusInId = source.connect('key-focus-in', () => {
- this._onMenuSourceEnter(menu);
- });
- }
-
if (position == undefined)
this._menus.push(menudata);
else
removeMenu(menu) {
if (menu == this.activeMenu)
- this._grabHelper.ungrab({ actor: menu.actor });
+ Main.popModal(menu.actor);
let position = this._findMenu(menu);
if (position == -1) // not a menu we manage
menu.disconnect(menudata.openStateChangeId);
menu.disconnect(menudata.destroyId);
- if (menudata.enterId)
- menu.sourceActor.disconnect(menudata.enterId);
- if (menudata.focusInId)
- menu.sourceActor.disconnect(menudata.focusInId);
-
- if (menu.sourceActor)
- this._grabHelper.removeActor(menu.sourceActor);
this._menus.splice(position, 1);
}
- get activeMenu() {
- let firstGrab = this._grabHelper.grabStack[0];
- if (firstGrab)
- return firstGrab.actor._delegate;
- else
- return null;
- }
-
ignoreRelease() {
- return this._grabHelper.ignoreRelease();
}
_onMenuOpenState(menu, open) {
+ if (open && this.activeMenu === menu)
+ return;
+
if (open) {
if (this.activeMenu)
this.activeMenu.close(BoxPointer.PopupAnimation.FADE);
- this._grabHelper.grab({
- actor: menu.actor,
- focus: menu.focusActor,
- onUngrab: isUser => this._closeMenu(isUser, menu),
- });
+ Main.pushModal(menu.actor, this._grabParams);
+ this.activeMenu = menu;
} else {
- this._grabHelper.ungrab({ actor: menu.actor });
+ if (this.activeMenu === menu)
+ this.activeMenu = null;
+ Main.popModal(menu.actor);
}
}
: BoxPointer.PopupAnimation.FULL);
}
- _onMenuSourceEnter(menu) {
- if (!this._grabHelper.grabbed)
- return Clutter.EVENT_PROPAGATE;
-
- if (this._grabHelper.isActorGrabbed(menu.actor))
- return Clutter.EVENT_PROPAGATE;
+ _onCapturedEvent(actor, event) {
+ let menu = actor._delegate;
+ if (event.type() === Clutter.EventType.KEY_PRESS) {
+ let symbol = event.get_key_symbol();
+ if (symbol === Clutter.KEY_Down &&
+ global.stage.get_key_focus() === menu.actor) {
+ actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
+ return Clutter.EVENT_STOP;
+ } else if (symbol === Clutter.KEY_Escape && menu.isOpen) {
+ menu.close(BoxPointer.PopupAnimation.FULL);
+ return Clutter.EVENT_STOP;
+ }
+ } else if (event.type() === Clutter.EventType.ENTER &&
+ (event.get_flags() & Clutter.EventFlags.GRAB_NOTIFY) === 0) {
+ let hoveredMenu = this._findMenuForSource(event.get_source());
+
+ if (hoveredMenu && hoveredMenu !== menu)
+ this._changeMenu(hoveredMenu);
+ } else if ((event.type() === Clutter.EventType.BUTTON_PRESS ||
+ event.type() === Clutter.EventType.TOUCH_BEGIN) &&
+ !actor.contains(event.get_source())) {
+ menu.close(BoxPointer.PopupAnimation.FULL);
+ }
- this._changeMenu(menu);
return Clutter.EVENT_PROPAGATE;
}
+ _findMenuForSource(source) {
+ while (source) {
+ let actor = source;
+ const menu = this._menus.map(m => m.menu).find(m => m.sourceActor === actor);
+ if (menu)
+ return menu;
+ source = source.get_parent();
+ }
+
+ return null;
+ }
+
_onMenuDestroy(menu) {
this.removeMenu(menu);
}